#ifndef XMLRPC_TYPES
#define XMLRPC_TYPES

#include <e32base.h>
#include <e32hashtab.h>

namespace XmlRpc
{
const TInt KGrowIncrement = 0x100;

typedef enum
	{
	EUnknown = 0,
	EInt = 1,
	EBoolean = 2,
	EDouble = 3,
	EDateTime = 4,
	EString = 5,
	EBase64 = 6,
	EArray = 7,
	EStruct = 8
	}
	TTypeId;

class CValue : public CBase
	{
public:
	IMPORT_C virtual ~CValue();
	IMPORT_C void AppendXmlToBufL(RBuf8& aBuf) const;
	IMPORT_C TTypeId TypeId() const { return iType; }
	
protected:
	CValue(TTypeId aType) : iType(aType) {}

	IMPORT_C virtual void DoAppendXmlToBufL(RBuf8& aBuf) const = 0 ;

	void InsureSpaceL(RBuf8& aBuf, TInt aCharacters) const;

private:
	TTypeId iType;
	};

template<typename CLASSNAME, typename TYPE, TTypeId TYPEID = EUnknown>
class CValueBase : public CValue
	{
public:
	static CLASSNAME* NewL(const TYPE& aVal)
		{
		return new(ELeave) CLASSNAME(aVal);
		}
	
	void Set(TYPE aVal) { iVal = aVal; }
	TYPE Get() const { return iVal; }

protected:
	CValueBase(const TYPE& aVal) : CValue(TYPEID), iVal(aVal)
		{}
	CValueBase() {}
	TYPE iVal;
	};

class CInt : public CValueBase<CInt, TInt, EInt>
	{
public:
	CInt(TInt aVal) : CValueBase(aVal) {}

protected:
	IMPORT_C virtual void DoAppendXmlToBufL(RBuf8& aBuf) const;
	};

class CBoolean : public CValueBase<CBoolean, TBool, EBoolean>
	{
public:
	CBoolean(TBool aVal) : CValueBase(aVal) {}

protected:
	IMPORT_C virtual void DoAppendXmlToBufL(RBuf8& aBuf) const;
	};

class CDouble : public CValueBase<CDouble, TReal, EDouble>
    {
public:
	CDouble(TReal aVal) : CValueBase(aVal) {}

protected:
	IMPORT_C virtual void DoAppendXmlToBufL(RBuf8& aBuf) const;
	};

class CDateTime : public CValueBase<CDateTime, TDateTime, EDateTime>
    {
public:
	CDateTime(TDateTime aVal) : CValueBase(aVal) {}

protected:
	IMPORT_C virtual void DoAppendXmlToBufL(RBuf8& aBuf) const;
	};

class CString : public CValue
	{
public:
	IMPORT_C static CString* NewL(const TDesC& aVal);
	
	IMPORT_C void SetL(const TDesC& aVal);
	IMPORT_C const TDesC& Get() const;
	
	IMPORT_C ~CString();
protected:
	void ConstructL(const TDesC& aVal);
	CString(const TDesC &aVal);
	CString();
	IMPORT_C virtual void DoAppendXmlToBufL(RBuf8& aBuf) const;

private:
	RBuf iString;
	};

class CBase64 : public CValue
    {
public:
	IMPORT_C static CBase64* NewL(const TDesC8& aVal);
	IMPORT_C static CBase64* NewFromEncodedL(const TDesC8& aVal);
		
	IMPORT_C void SetL(const TDesC8& aVal);
	IMPORT_C const TDesC8& Get() const;
	IMPORT_C const TDesC8& GetEncodedL() const;
	
	IMPORT_C ~CBase64();

protected:
	void ConstructL(const TDesC8& aVal, TBool aEncoded);
	CBase64(const TDesC8 &aVal);
	CBase64();
	
	IMPORT_C virtual void DoAppendXmlToBufL(RBuf8& aBuf) const;
	
private:
	RBuf8 iString;
	mutable RBuf8 iEncoded;
	};

const TInt KMaxKeyLen = 256;
class CStruct : public CValue
	{	
public:
	typedef TBuf8<KMaxKeyLen> TStructKey;
	
	IMPORT_C static CStruct* NewL();

	/**
	 * Takes ownership of member
	 */
	IMPORT_C void SetL(const TDesC8& aKey, CValue* aMember);
	IMPORT_C CValue* GetL(const TDesC8& aKey) const;
	IMPORT_C CValue* RemoveL(const TDesC8& aKey);
	IMPORT_C ~CStruct();
	
protected:	
	IMPORT_C virtual void DoAppendXmlToBufL(RBuf8& aBuf) const;

private:
	CStruct();

	RHashMap<const TStructKey, CValue*> iMembers;
	};

class CArray : public CValue
	{
public:
	IMPORT_C static CArray* NewL();

	IMPORT_C void InsertL(CValue* aVal, TInt aIndex);
	IMPORT_C void AppendL(CValue* aVal);
	IMPORT_C TInt Count() const;
	IMPORT_C CValue* Get(TInt aIndex) const;
	IMPORT_C CValue* RemoveL(TInt aIndex);

	IMPORT_C ~CArray();
	
protected:
	IMPORT_C virtual void DoAppendXmlToBufL(RBuf8& aBuf) const;

private:
	CArray();
	
	RPointerArray<CValue> iArray;
	};
}

#endif
